package org.lex.keytool.ui;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;

import org.lex.keytool.core.service.TaskService;
import org.lex.keytool.core.task.Task;
import org.lex.keytool.ui.builder.TaskPaneBuilder;
import org.lex.keytool.ui.task.BaseTaskPane;

public class WorkspacePane extends JPanel {
	private static final Border BORDER = new EmptyBorder(5, 5, 5, 5);

	private JPanel titlePane = null;
	private JLabel titleLabel = null;

	private JPanel taskPane = null;
	private JPanel buttonsPane = null;
	private JButton restoreDefaultButton = null;
	private JButton runButton = null;

	private String EMPTY_NAME = new Date().toString();
	private BaseTaskPane currentTaskPane = new EmptyPane();
	private JScrollPane emptyPane = new JScrollPane(currentTaskPane);
	private CardLayout cardLayout = new CardLayout();

	private Map<Class<? extends Task>, JScrollPane> taskPaneCache = new HashMap<Class<? extends Task>, JScrollPane>();
	private Map<JScrollPane, String> paneNames = new HashMap<JScrollPane, String>();

	public WorkspacePane() {
		super(new BorderLayout(0, 5));
		this.initComponents();
	}

	public void setTaskClass(Class<? extends Task> taskClass) {
		String title = null;
		JScrollPane pane = null;
		String name = null;
		if (null == taskClass) {
			title = "No Task";
			name = EMPTY_NAME;
			pane = emptyPane;
		} else {
			title = TaskService.getInstance().getTaskName(taskClass);
			pane = taskPaneCache.get(taskClass);
			if (null == pane) {
				pane = new JScrollPane(new TaskPaneBuilder().createTaskPane(taskClass));
				taskPaneCache.put(taskClass, pane);
			}
			name = paneNames.get(pane);
			if (null == name) {
				name = Double.toString(Math.random());
				paneNames.put(pane, name);
				this.getTaskPane().add(pane, name);
			}
		}
		this.currentTaskPane = (BaseTaskPane) pane.getViewport().getView();
		this.getTitleLabel().setText(title);
		pane.setBorder(BORDER);
		cardLayout.show(this.getTaskPane(), name);
	}

	private void initComponents() {
		this.add(this.getTitlePane(), BorderLayout.NORTH);
		this.add(this.getTaskPane(), BorderLayout.CENTER);
		this.add(this.getButtonsPane(), BorderLayout.SOUTH);
		this.setBorder(new EmptyBorder(12, 11, 0, 11));
	}

	private JPanel getTitlePane() {
		if (null == titlePane) {
			titlePane = new JPanel(new GridBagLayout());
			GridBagConstraints gc;

			gc = new GridBagConstraints();
			gc.gridx = 0;
			gc.gridy = 0;
			gc.fill = GridBagConstraints.HORIZONTAL;
			gc.weightx = 10.0;
			titlePane.add(this.getTitleLabel(), gc);

			gc = new GridBagConstraints();
			gc.gridx = 0;
			gc.gridy = 1;
			gc.fill = GridBagConstraints.HORIZONTAL;
			gc.weightx = 10.0;
			titlePane.add(new JSeparator(), gc);
		}
		return titlePane;
	}

	private JLabel getTitleLabel() {
		if (null == titleLabel) {
			titleLabel = new JLabel("No Task");
			Font f = titleLabel.getFont();
			titleLabel.setFont(f.deriveFont(Font.BOLD, f.getSize2D() + 10));
		}
		return titleLabel;
	}

	private JPanel getTaskPane() {
		if (null == taskPane) {
			taskPane = new JPanel(cardLayout);
			emptyPane.setBorder(BORDER);
			taskPane.add(emptyPane, EMPTY_NAME);
			paneNames.put(emptyPane, EMPTY_NAME);
		}
		return taskPane;
	}

	private JPanel getButtonsPane() {
		if (null == buttonsPane) {
			FlowLayout layout = new FlowLayout(FlowLayout.RIGHT, 5, 5);
			layout.setAlignOnBaseline(true);
			buttonsPane = new JPanel(layout);
			buttonsPane.add(this.getRestoreDefaultButton());
			buttonsPane.add(this.getRunButton());
		}
		return buttonsPane;
	}

	private JButton getRestoreDefaultButton() {
		if (null == restoreDefaultButton) {
			restoreDefaultButton = new JButton();
			restoreDefaultButton.setAction(new RestoreDefaultAction());
		}
		return restoreDefaultButton;
	}

	private JButton getRunButton() {
		if (null == runButton) {
			runButton = new JButton();
			runButton.setAction(new RunAction());
		}
		return runButton;
	}

	private class RestoreDefaultAction extends BaseAction {
		public RestoreDefaultAction() {
			this.setName("Restore Defaults");
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			currentTaskPane.restoreDefault();
		}
	}

	private class RunAction extends BaseAction {
		public RunAction() {
			this.setName("Run");
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			currentTaskPane.run();
		}
	}
}
